package cn.stard.basic.service.impl;

import cn.stard.basic.constants.BaseConstants;
import cn.stard.basic.dto.SmsCodeDot;
import cn.stard.basic.exception.BusinessException;
import cn.stard.basic.service.VerifyCodeService;
import cn.stard.basic.util.SmsUtils;
import cn.stard.basic.util.StrUtils;
import cn.stard.basic.util.VerifyCodeUtils;
import cn.stard.user.domain.User;
import cn.stard.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements VerifyCodeService {

@Autowired
private RedisTemplate  redisTemplate;
@Autowired
private UserMapper userMapper;
    @Override
    public String getImageCode(String imageCodeKey) {
        /*1判断参数是否为空*/
        if (StringUtils.isEmpty(imageCodeKey)){
            throw  new BusinessException("请传递必要参数");
        }
        /*  2.调用字符串工具类方法获取随机4为字符串*/
        String code = StrUtils.getComplexRandomString(4);
            /*3.将随机字符串设置到redis中imageCodeKey就是传递进来的imageCodeKey值并设置时间为5分钟*/
        redisTemplate.opsForValue().set(imageCodeKey,code,5, TimeUnit.MINUTES);

        /*4.将code值生成图形并编码为Base64 */
        String base64stf = VerifyCodeUtils.VerifyCode(100, 35, code);
        return base64stf;
    }

    @Override
    public void smsCode(SmsCodeDot smsCodeDot) {
        // 0.获取前端发送的请求的数据做出相应的判断
        String phone = smsCodeDot.getPhone();
        /*验证码业务类型type*/
        String type = smsCodeDot.getType();
        // 1.非空校验
        if(StringUtils.isEmpty(phone)||StringUtils.isEmpty(type)){
            throw new BusinessException("输入的主要参数不能为空");
        }
        // 2.判断点击获取的时候是那个业务
        // 2.1.注册业务
        if ("register".equals(type)){
            // 校验图形验证码是否正确
            checkImageCode(smsCodeDot);
            User user = userMapper.loadByPhone(phone);

            //3.判断用户是否已注册，如果已注册提示用户
            if (user!=null) {
                throw new BusinessException("用户已注册，请直接登录，如果忘记密码，请点击忘记密码！");
            }
            sendCode(BaseConstants.VerifyConstants.BUSINESS_REGISTER_KEY,phone);
        }else if ("binder".equals(type)) {//如果是微信绑定业务,直接发送短信验证码
            sendCode(BaseConstants.VerifyConstants.BUSINESS_BINDER_KEY,phone);
        }


    }
        /*抽取图形验证方便在判断业务的时候调用*/
    public void checkImageCode(SmsCodeDot smsCodeDot){
        // 获取图形验证码的key
        String imageCodeKey = smsCodeDot.getImageCodeKey();
        // 获取图形验证码的value
        String imageCodeValue = smsCodeDot.getImageCodeValue();
        // 进行非空校验
        if (StringUtils.isEmpty(imageCodeKey) || StringUtils.isEmpty(imageCodeValue)){
            throw new BusinessException("输入参数不能为空！");
        }
        // 判断图形验证码是否正确或者存在
        Object imageCodeValueTmp  = redisTemplate.opsForValue().get(imageCodeKey);
        if (imageCodeValueTmp==null){
            throw new BusinessException("验证码已过期，请重新获取！");
        }
        // 忽略大小写比较图形验证码是否正确
        if (!imageCodeValueTmp.toString().equalsIgnoreCase(imageCodeValue)){
            throw new BusinessException("验证码错误，请重新输入！");
        }
    }

    public void sendCode(String businessKey, String phone){
        // 根据电话号码拼接业务键.去redis中获取值,判断是否存在
       String phoneCodeKey = businessKey+phone;
        Object phoneCodeValue  = redisTemplate.opsForValue().get(phoneCodeKey);
        // 0定义一个字符串,用来接收验证码
        String phoneCode = "";
        if (phoneCodeValue == null){//1.不存在
            //1.生成新的随机验证码,并赋值给空字符串
            phoneCode = StrUtils.getComplexRandomString(4);
        }else {//2.存在
            //1.分割value得到时间戳，跟现在的时间戳做减法，如果小于1分钟的毫秒数抛出异常
            String[] phoneCodeValueTmp = phoneCodeValue.toString().split(":");
            // 之前存入code时，我们记录的时间戳
            Long oldTime = Long.valueOf(phoneCodeValueTmp[0]);
            // 现在的时间戳
            Long nowTime = System.currentTimeMillis();
            if (nowTime - oldTime < 1*60*1000){
                throw new BusinessException("请一分钟之后再获取！");
            }
            //2.将旧的验证码赋值给空字符串
            phoneCode = phoneCodeValueTmp[1];
        }
        //5.通过业务键+phone作为key，验证码+时间戳作为value，存入redis，设置为三分钟有效
        String phoneCodeRedis = System.currentTimeMillis() + ":" + phoneCode;
        redisTemplate.opsForValue().set(phoneCodeKey, phoneCodeRedis, 3, TimeUnit.MINUTES);
        //6.发送短信验证码
        // SmsUtils.sendCode(phone, "亲，您的验证码是："+ phoneCode);
        System.out.println("亲，您的验证码是："+ phoneCode);
    }

}



//    @Override
//    public void smsCode(SmsCodeDot smsCodeDot) {
//        // 0.获取前端发送的请求的数据做出相应的判断
//        String phone = smsCodeDot.getPhone();
//        String imageCodeKey = smsCodeDot.getImageCodeKey();
//        String imageCodeValue = smsCodeDot.getImageCodeValue();
//        // 1判断主要参数是否非空
//        if (    StringUtils.isEmpty(phone)
//                || StringUtils.isEmpty(imageCodeKey)
//                || StringUtils.isEmpty(imageCodeValue)){
//            throw new BusinessException("参数为空请重新输入");
//       }
//
//        // 2判断图形参数是否存在
//        /*2,1通过redis里存的k值来获得v的值*/
//        Object imageCodeValueTmp = redisTemplate.opsForValue().get(imageCodeKey);
//            if (imageCodeValueTmp==null){
//                throw new BusinessException("图形验证码已过期请重新获取");
//            }
//        // 3 判断图形验证码是否正确用忽略大小写的方式
//        if (!imageCodeValueTmp.toString().equalsIgnoreCase(imageCodeValue)){
//            throw new BusinessException("验证码错误,请重新输入!");
//        }
//        // 4 判断用户是否注册
//        User user = userMapper.loadByPhone(phone);
//        if (user!=null){
//            throw new BusinessException("账户已注册,请直接登录,如果忘记密码,请点击忘记密码.");
//        }
//    //4.根据电话号码拼接业务键，去redis中获取对应的value值，判断是否存在
//         // 通过工具类里的业务键设置为key值
//    String phoeCodeKey =     BaseConstants.VerifyConstants.BUSINESS_REGISTER_KEY+phone;
//        Object phoecodeValue = redisTemplate.opsForValue().get(phoeCodeKey);
//        // 定义一个空字符串,接收验证码
//        String phoneCode="";
//        // 判断验证码是否存在
//        if (phoecodeValue==null){// 判断验证码如果不存在
//            // 创建新的验证码并且赋值长度
//             phoneCode = StrUtils.getComplexRandomString(4);
//        }else {// 反之说明它存在
//            // 分割value的值获得时间戳,与现在的时间戳做减法,如果小于1分钟的毫秒数就抛出异常
//            String[] phoneCodeValueTmp = phoecodeValue.toString().split(":");
//            // 获取之前我们创建code时的时间戳并且转换类型
//         //   这样就获得了之前的时间
//            Long oldTime = Long.valueOf(phoneCodeValueTmp[0]);
//            // 获取当前的时间戳
//            long nowTime = System.currentTimeMillis();
//            // 用现在的时间戳获取的到毫秒数减去以前的毫秒数
//            if (nowTime- oldTime.intValue()<1*60*1000){
//                throw  new BusinessException(("请一分钟后再来获取"));
//            }
//            // 2.将旧代码放入字符串
//            phoneCode =phoneCodeValueTmp[1];
//        }
//        // 5.通过业务键+phone作为key,验证码+时间戳作为value,存入redis,设置为三分钟有效
//      String   phoneCoderedis=   System.currentTimeMillis()+":"+phoneCode;
//        redisTemplate.opsForValue().set(phoeCodeKey,phoneCoderedis,3,TimeUnit.MINUTES);
//        // 发送短信验证码
//             SmsUtils.sendCode(phone, "亲，您的验证码是："+ phoneCode);
//        System.out.println("亲，您的验证码是："+ phoneCode);
//    }





